package com.example.designpatterns.strategy;

import com.example.designpatterns.strategy.payment.AlipayStrategy;
import com.example.designpatterns.strategy.payment.CreditCardStrategy;
import com.example.designpatterns.strategy.payment.ShoppingCart;
import com.example.designpatterns.strategy.payment.WeChatPayStrategy;
import com.example.designpatterns.strategy.sorting.*;

import java.util.Arrays;
import java.util.Random;

/**
 * 策略模式演示类
 */
public class StrategyPatternDemo {

    public static void main(String[] args) {
        System.out.println("策略模式演示");
        System.out.println("=================");
        
        // 1. 排序策略示例
        System.out.println("\n1. 排序策略示例：");
        demonstrateSortingStrategies();
        
        // 2. 支付策略示例
        System.out.println("\n2. 支付策略示例：");
        demonstratePaymentStrategies();
    }
    
    /**
     * 演示排序策略
     */
    private static void demonstrateSortingStrategies() {
        // 创建随机数组
        int[] array = generateRandomArray(20, 100);
        System.out.println("原始数组: " + Arrays.toString(array));
        System.out.println("数组长度: " + array.length);
        
        // 创建上下文
        Context<int[], int[]> sortContext = new Context<>(null);
        
        // 测试所有排序策略
        testSortStrategy(sortContext, "冒泡排序", new BubbleSortStrategy(), array);
        testSortStrategy(sortContext, "选择排序", new SelectionSortStrategy(), array);
        testSortStrategy(sortContext, "插入排序", new InsertionSortStrategy(), array);
        testSortStrategy(sortContext, "希尔排序", new ShellSortStrategy(), array);
        testSortStrategy(sortContext, "归并排序", new MergeSortStrategy(), array);
        testSortStrategy(sortContext, "快速排序", new QuickSortStrategy(), array);
        testSortStrategy(sortContext, "堆排序", new HeapSortStrategy(), array);
        testSortStrategy(sortContext, "计数排序", new CountingSortStrategy(), array);
        testSortStrategy(sortContext, "桶排序", new BucketSortStrategy(), array);
        testSortStrategy(sortContext, "基数排序", new RadixSortStrategy(), array);
        
        // 性能对比测试（使用更大的数组）
        System.out.println("\n排序算法性能对比测试（大数组）：");
        compareSortingPerformance();
    }
    
    /**
     * 测试单个排序策略
     * @param context 策略上下文
     * @param name 策略名称
     * @param strategy 排序策略
     * @param array 待排序数组
     */
    private static void testSortStrategy(
            Context<int[], int[]> context, 
            String name, 
            Strategy<int[], int[]> strategy, 
            int[] array) {
        context.setStrategy(strategy);
        
        System.out.println("\n使用" + name + ":");
        long startTime = System.nanoTime();
        int[] sortedArray = context.executeStrategy(array);
        long endTime = System.nanoTime();
        
        System.out.println("排序后: " + Arrays.toString(sortedArray));
        System.out.println("耗时: " + (endTime - startTime) / 1000 + " 微秒");
        
        // 验证排序结果是否正确
        boolean isSorted = isSorted(sortedArray);
        System.out.println("排序正确: " + (isSorted ? "是" : "否"));
    }
    
    /**
     * 对比不同排序算法的性能
     */
    private static void compareSortingPerformance() {
        // 创建更大的随机数组进行性能测试
        int[] largeArray = generateRandomArray(10000, 10000);
        
        // 创建策略上下文
        Context<int[], int[]> context = new Context<>(null);
        
        // 排序策略数组
        @SuppressWarnings("unchecked")
        Strategy<int[], int[]>[] strategies = new Strategy[] {
            new BubbleSortStrategy(),
            new SelectionSortStrategy(),
            new InsertionSortStrategy(),
            new ShellSortStrategy(),
            new MergeSortStrategy(),
            new QuickSortStrategy(),
            new HeapSortStrategy(),
            new CountingSortStrategy(),
            new BucketSortStrategy(),
            new RadixSortStrategy()
        };
        
        // 策略名称数组
        String[] strategyNames = {
            "冒泡排序", "选择排序", "插入排序", "希尔排序", 
            "归并排序", "快速排序", "堆排序", "计数排序", 
            "桶排序", "基数排序"
        };
        
        System.out.println("数组大小: " + largeArray.length + " 元素");
        
        // 测量每种排序算法的性能
        for (int i = 0; i < strategies.length; i++) {
            context.setStrategy(strategies[i]);
            
            long startTime = System.nanoTime();
            int[] sorted = context.executeStrategy(largeArray);
            long endTime = System.nanoTime();
            
            long duration = (endTime - startTime) / 1000000; // 转换为毫秒
            System.out.println(strategyNames[i] + ": " + duration + " 毫秒 " + 
                    (isSorted(sorted) ? "✓" : "✗"));
        }
    }
    
    /**
     * 验证数组是否已排序
     * @param array 待验证数组
     * @return 如果已排序返回true，否则返回false
     */
    private static boolean isSorted(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 演示支付策略
     */
    private static void demonstratePaymentStrategies() {
        // 创建购物车
        ShoppingCart cart = new ShoppingCart();
        
        // 添加商品
        cart.addItem(new ShoppingCart.Item("Java核心技术卷I", 95.0, 1));
        cart.addItem(new ShoppingCart.Item("设计模式", 85.0, 1));
        cart.addItem(new ShoppingCart.Item("算法导论", 128.0, 1));
        
        // 使用信用卡支付
        System.out.println("\n使用信用卡支付:");
        cart.setPaymentStrategy(new CreditCardStrategy("张三", "1234567890123456", "123", "12/25"));
        cart.checkout();
        
        // 使用支付宝支付
        System.out.println("\n使用支付宝支付:");
        cart.setPaymentStrategy(new AlipayStrategy("zhangsan@example.com", "password"));
        cart.checkout();
        
        // 使用微信支付
        System.out.println("\n使用微信支付:");
        cart.setPaymentStrategy(new WeChatPayStrategy("zhangsan12345", "wx_token_123"));
        cart.checkout();
    }
    
    /**
     * 生成指定长度的随机整数数组
     * @param size 数组长度
     * @param maxValue 最大值
     * @return 随机整数数组
     */
    private static int[] generateRandomArray(int size, int maxValue) {
        Random random = new Random();
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = random.nextInt(maxValue);
        }
        return array;
    }
} 